% 
% @(#)phoney_Array.m	1.1  3/6/87
%
export _ArrayObject to "Builtins"

const _ArrayObject == 
  immutable object _ArrayObject
    export of
    function of [ElementType : AbstractType] -> [result : NAT]
      where
	NAT ==	immutable type NAT
		  operation empty -> [NA]
%		  operation literal [Vector.of[ElementType]] -> [NA]
		  operation create[Integer] -> [NA]
		  function getSignature -> [Signature]
		end NAT
	NA ==	type NA
		  function  getElement [Integer] -> [ElementType]
		    % get the element indexed by index, failing if index 
		    % out of range.
		  operation setElement [Integer, ElementType]
		    % set the element, failing if index out of range
		  function  upperbound -> [Integer]
		    % return the highest valid index, ub.
		  function  lowerbound -> [Integer]
		    % return the lowest valid index, lb.
		  function  getSlice [Integer, Integer] -> [NA]
		    % return a new array, a, with lower bound lb, and 
		    % upper bound ub, such that for lb <= i <= ub:
		    %     self.getElement[i] == a.getElement[i]
		    % fail if lb or ub is out of range.
		  operation setSlice [Integer, Integer, NA]
		    % set the elements indexed by i for lb <= i <= ub, so 
		    % that for each such i:
		    %     self.getElement[i] == a.getElement[i]
		    % fail if lb or ub is out of range.
		  operation slideTo [Integer]
		    % change the valid indicies for self.  Assuming 
		    % the old indicies ranged from lb to ub, the new 
		    % indicies will range from i to i + ub - lb
		  operation addUpper [ElementType]
		    % extend the set of valid indicies, changing ub to 
		    % ub + 1, and setting the element indexed by the new
		    % ub to be e.
		  operation removeUpper -> [ElementType]
		    % return the element indexed by ub, after contracting 
		    % the set of valid indicies to lb <= i <= ub - 1.
		  operation addLower [ElementType]
		    % extend the set of valid indicies, changing lb to 
		    % lb - 1, and setting
		    % the element indexed by the new lb to be e.
		  operation removeLower -> [ElementType]
		    % return the element indexed by lb, after contracting 
		    % the set of valid indicies to lb + 1 <= i <= ub.
		  function  empty -> [Boolean]
		    % -> true if lb == ub + 1, which is true initially,
		    % since initially lb = 1, and ub = 0.
		  operation catenate [a : NA] -> [r : NA]
		    % extend the range of valid indicies from lb .. ub to 
		    % lb .. ub + a.length.  Set these new elements to refer
		    % to the elements of a so that for a.lb <= i <= a.ub, 
		    % where oub is the old value of self.ub:
		    %     a.getElement[i] == self.getElement[oub + i - 1]
		end NA
	ElementType *> type T end T
      end where

      result <- 
	immutable object aNAT
	  export empty, create, getSignature

	  function getSignature -> [result : Signature]
	    result <- NA
	  end getSignature

	  operation create[length : Integer] -> [result : NA]
	    result <-
	      object aNA
		export getElement, setElement, upperbound, lowerbound, getSlice, setSlice,
		       slideTo, addUpper, removeUpper, addLower,
		       removeLower, empty, catenate

		var lb : Integer
		var ub : Integer
%		var vec: Vector.of[ElementType]

		function  getElement [index : Integer] -> [result : ElementType]
		  % get the element indexed by index, failing if index 
		  % out of range.
		  primitive 002 [result] <- [index]
		end getElement
		operation setElement [i : Integer, r : ElementType]
		  % set the element, failing if index out of range
		  primitive 102 [] <- [i, r]
		end setElement
		function  upperbound -> [r : Integer]
		  % return the highest valid index, ub.
		  primitive 202 [r] <- []
		end upperbound
		function  lowerbound -> [r : Integer]
		  % return the lowest valid index, always 1.
		  primitive 302 [r] <- []
		end lowerbound
		function  getSlice [i1 : Integer, i2 : Integer] -> [r : NA]
		  % return a new Vector, a, with lower bound lb, and 
		  % upper bound ub, such that for lb <= i <= ub:
		  %     self.getElement[i] == a.getElement[i]
		  % fail if lb or ub is out of range.
		  primitive 402 [r] <- [i1, i2]
		end getSlice
		operation setSlice [i1 : Integer, i2 : Integer, s : NA]
		  % set the elements indexed by i for lb <= i <= ub, so 
		  % that for each such i:
		  %     self.getElement[i] == a.getElement[i]
		  % fail if lb or ub is out of range.
		  primitive 502 [] <- [i1, i2, s]
		end setSlice
		operation slideTo [i : Integer]
		  % change the valid indicies for self.  Assuming 
		  % the old indicies ranged from lb to ub, the new 
		  % indicies will range from i to i + ub - lb
		  primitive 602 [] <- [i]
		end slideTo
		operation addUpper [e : ElementType]
		  % extend the set of valid indicies, changing ub to 
		  % ub + 1, and setting the element indexed by the new
		  % ub to be e.
		  primitive 702 [] <- [e]
		end addUpper
		operation removeUpper -> [r : ElementType]
		  % return the element indexed by ub, after contracting 
		  % the set of valid indicies to lb <= i <= ub - 1.
		  primitive 802 [] <- [r]
		end removeUpper
		operation addLower [e : ElementType]
		  % extend the set of valid indicies, changing lb to 
		  % lb - 1, and setting
		  % the element indexed by the new lb to be e.
		  primitive 902 [] <- [e]
		end addLower
		operation removeLower -> [r : ElementType]
		  % return the element indexed by lb, after contracting 
		  % the set of valid indicies to lb + 1 <= i <= ub.
		  primitive 1002 [r] <- []
		end removeLower
		function  empty -> [r : Boolean]
		  % -> true if lb == ub + 1, which is true initially,
		  % since initially lb = 1, and ub = 0.
		  primitive 1102 [r] <- []
		end empty
		operation catenate [a : NA] -> [r : NA]
		  % return a new vector the result of catenating the 
		  % elements of a to self
		  primitive 1202 [r] <- [a]
		end catenate
	      end aNA
	  end create
	  operation empty -> [result : NA]
	    result <- aNAT.create[10]
	  end empty
	end aNAT
    end of

  end _ArrayObject
